package pro.survey.analyzer;

import java.util.ArrayList;
import java.util.List;
import javafx.scene.chart.BarChart;
import pro.survey.analyzer.data.Answers;
import pro.survey.analyzer.data.Imports;
import pro.survey.analyzer.data.Lectors;
import pro.survey.analyzer.data.Series;
import pro.survey.analyzer.exceptions.InvalidNumberItemsAndValues;
import pro.survey.analyzer.lectors.window.LectorCheckBox;
import pro.survey.analyzer.lectors.window.LectorsWindow;

/**
 *
 * @author Adrian
 */
public class AnalyticsEngine {

    public static final String CLASSROOM_ATMOSPHERE_QUESTION = "Czy opowiada Panu/Pani atmosfera na zajęciach?";
    public static final String WORKING_METHOD_QUESTION = "Czy podoba się Pani/u sposób pracy lektora?";
    public static final String EXPLANING_GRAMMAR_QUESTION = "Czy lektor w sposób przystępny wyjaśnia nowe zagadnienia językowe?";
    public static final String PLAYING_CD_QUESTION = "Wykorzystanie odtwarzacza CD";
    public static final String PLAYING_DVD_QUESTION = "Wykorzystanie odtwarzacza DVD";
    public static final String USEING_PROJECTOR_QUESTION = "Wykorzystanie odtwarzacza rzutnika / sali komp.";
    public static final String HOMEWORKS_QUESTION = "Czy lektor sprawdza zadane prace pisemne?";
    public static final String EFFICIENT_USE_TIME_QUESTION = "Czy czas na zajęciach jest wykorzystywany efektywnie?";
    public static final String POLISH_SPEAKING_QUESTION = "Czy Pani/a zdaniem na zajęcich mówi sie po polsku?";
    public static final String LEARNING_STYLE_QUESTION = "Czy na zajęciach został określony Pani/a styl uczenia się?";
    public static final String MADE_PROGRESS_QUESTION = "Czy ma Pan/i poczucie czynionych postępów?";
    public static final String YOUR_TIME_LEARNING_QUESTION = "Ile czasu w tygodniu przeznacza Pan/ Pani na pracę własną nad językiem?";
    public static final String LISEN_ZONE_QUESTION = "Czy korzysta Pani/ Pan ze strefy słuchacza (e - campus) na www. empikschool.com ?";
    public static final String USE_LECTOR_BLOG_QUESTION = "Czy pani/ Pan korzysta z bloga lektorskiego?";
    public static final String LECTOR_RATE_QUESTION = "Jaką ogólna ocenę wystawiłaby/by Pani/ Pan lektorowi?";
    public static final String ALLWAYS_RATE = "zawsze";
    public static final String OFTEN_RATE = "często";
    public static final String SOMETIMES_RATE = "czasami";
    public static final String NEVER_RATE = "nigdy";
    public static final String TOO_MUCH_RATE = "za dużo";
    public static final String NOT_LESS_NOT_MUCH_RATE = "w sam raz";
    public static final String TOO_LESS_RATE = "za mało";
    public static final String EMPTY_RATE = "w ogóle";
    public static final String YES_RATE = "tak";
    public static final String NO_RATE = "nie";
    public static final String TIME_LEARNING_MORE_HOUR_RATE = "więcej niż 1 godz.";
    public static final String TIME_LEARNING_HOUR_RATE = "60 min.";
    public static final String TIME_LEARNING_30_MIN_RATE = "45-30 min.";
    public static final String TIME_LEARNING_20_MIN_RATE = "30- 20 min.";
    public static final String TIME_LEARNING_LESS_20_MIN_RATE = "mniej niż 20 min.";
    public static final String RATE_6 = "wybitną";
    public static final String RATE_5 = "bardzo dobrą";
    public static final String RATE_4 = "dobrą";
    public static final String RATE_3 = "dostateczną";
    public static final String RATE_2 = "niedostateczną";
    private Imports imp;
    private static AnalyticsEngine instance = null;

    private AnalyticsEngine() {
    }

    public static AnalyticsEngine getInstance() {
        if (instance == null) {
            instance = new AnalyticsEngine();
        }
        return instance;
    }

    public void setImport(Imports imp) {
        this.imp = imp;
    }

    public Imports getImport() {
        return this.imp;
    }

    public List<BarChartWithNote> makeChartByQuestion() {
        List<Integer> lectorsIds = new ArrayList<Integer>();
        for (LectorCheckBox cb : LectorsWindow.getInstance().getCbs()) {
            if (cb.isSelected()) {
                lectorsIds.add(cb.getLectorId());
            }
        }
        List<Object[]> lectorsAnswers = HibernateUtil.getSession().createQuery("from Lectors l left join l.answerses a where l.id IN (:lectors) order by a.questions, a.lectors asc")
                .setParameterList("lectors", lectorsIds.toArray())
                .list();
        List<BarChartWithNote> charts = new ArrayList<BarChartWithNote>();
        
        int lastQuestionId = -1;
        int lastLectorId = -1;
        int sumResponents = -1;
        Series s = null;
        for (Object[] lectorAnswer : lectorsAnswers) {
            Lectors lector = (Lectors) lectorAnswer[0];
            Answers answer = (Answers) lectorAnswer[1];
            if (answer.getQuestions().getId() != lastQuestionId) {
                if (s instanceof Series) {
                    double i = s.getValues().get(s.getValues().size() - 1);
                    i = i / sumResponents;
                    s.getValues().remove(s.getValues().size() - 1);
                    s.getValues().add(i);
                    sumResponents = 0;
                    charts.add(RenderCharts.createBarChart(getShortQuestion(answer.getQuestions().getText()), null, null, s));
                }
                s = new Series();
                s.setTitle(answer.getQuestions().getText());
            }
            if (lastLectorId == lector.getId()) {
                double i = s.getValues().get(s.getValues().size() - 1);
                s.getValues().remove(s.getValues().size() - 1);
                i += parseValue(answer.getType(), answer.getValue());
                s.getValues().add(i);
            } else {
                if (s.getValues().size() > 0) {
                    double i = s.getValues().get(s.getValues().size() - 1);
                    i = i / sumResponents;
                    s.getValues().remove(s.getValues().size() - 1);
                    s.getValues().add(i);
                    sumResponents = 0;
                }
                s.getItems().add(lector.getName().concat(" ").concat(lector.getSurname()));
                s.getValues().add(parseValue(answer.getType(), answer.getValue()));
            }
            lastLectorId = lector.getId();
            lastQuestionId = answer.getQuestions().getId();
            sumResponents += Integer.parseInt(answer.getValue());
        }
        if (s instanceof Series) {
            double i = s.getValues().get(s.getValues().size() - 1);
            i = i / sumResponents;
            s.getValues().remove(s.getValues().size() - 1);
            s.getValues().add(i);
            Object[] lectorAnswer = lectorsAnswers.get(lectorsAnswers.size()-1);
            Answers answer = (Answers) lectorAnswer[1];
            charts.add(RenderCharts.createBarChart(getShortQuestion(answer.getQuestions().getText()), null, null, s));
        }
        return charts;
    }

    public BarChart makeMainChart() throws InvalidNumberItemsAndValues {
        List<Integer> lectorsIds = new ArrayList<Integer>();
        for (LectorCheckBox cb : LectorsWindow.getInstance().getCbs()) {
            if (cb.isSelected()) {
                lectorsIds.add(cb.getLectorId());
            }
        }
        List<Object[]> lectorsAnswers = HibernateUtil.getSession().createQuery("from Lectors l left join l.answerses a where l.id IN (:lectors)")
                .setParameterList("lectors", lectorsIds.toArray())
                .list();
        List<Series> series = new ArrayList<Series>();
        int lastLectorId = -1;
        int lastQuestionId = -1;
        int sumResponents = -1;
        Series s;
        Series average = new Series();
        average.setTitle(GUIGenerator.getInstance().getLocaleText(Trans.AVERAGE));
        Double i;
        for (Object[] lectorAnswer : lectorsAnswers) {
            Lectors lector = (Lectors) lectorAnswer[0];
            Answers answer = (Answers) lectorAnswer[1];
            if (lector.getId() == lastLectorId) {
                s = series.get(series.size() - 1);
            } else {
                if (series.size() > 0) {
                    s = series.get(series.size() - 1);
                    if (s instanceof Series) {
                        i = s.getValues().get(s.getValues().size() - 1);
                        i = i / sumResponents;
                        s.getValues().remove(s.getValues().size() - 1);
                        s.getValues().add(i);
                        sumResponents = 0;
                    }
                }
                s = new Series();
                s.setTitle(lector.getName().concat(" ").concat(lector.getSurname()));
            }
            if (lastQuestionId == answer.getQuestions().getId()) {
                i = s.getValues().get(s.getValues().size() - 1);
                s.getValues().remove(s.getValues().size() - 1);
                i += parseValue(answer.getType(), answer.getValue());
                s.getValues().add(i);
            } else {
                if (s.getValues().size() > 0) {
                    i = s.getValues().get(s.getValues().size() - 1);
                    s.getValues().remove(s.getValues().size() - 1);
                    i /= sumResponents;
                    s.getValues().add(i);
                    sumResponents = 0;
                }
                s.getItems().add(getShortQuestion(answer.getQuestions().getText()));
                s.getValues().add(parseValue(answer.getType(), answer.getValue()));
            }
            sumResponents += Integer.parseInt(answer.getValue());
            lastQuestionId = answer.getQuestions().getId();
            if (lector.getId() != lastLectorId) {
                series.add(s);
            }
            lastLectorId = lector.getId();
        }
        if (series.size() > 0) {
            s = series.get(series.size() - 1);
            if (s instanceof Series) {
                i = s.getValues().get(s.getValues().size() - 1);
                i = i / sumResponents;
                s.getValues().remove(s.getValues().size() - 1);
                s.getValues().add(i);
            }
        }
        return RenderCharts.createBarChartSeries(GUIGenerator.getInstance().getLocaleText(Trans.MAIN_CHART), null, null, series);
    }

    private String getShortQuestion(String question) {
        switch (question) {
            case CLASSROOM_ATMOSPHERE_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.CLASSROOM_ATMOSPHERE_SHORT_QUESTION);
            case EFFICIENT_USE_TIME_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.EFFICIENT_USE_TIME_SHORT_QUESTION);
            case EXPLANING_GRAMMAR_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.EXPLANING_GRAMMAR_SHORT_QUESTION);
            case HOMEWORKS_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.HOMEWORKS_SHORT_QUESTION);
            case LEARNING_STYLE_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.LEARNING_STYLE_SHORT_QUESTION);
            case LECTOR_RATE_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.LECTOR_RATE_SHORT_QUESTION);
            case LISEN_ZONE_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.LISEN_ZONE_SHORT_QUESTION);
            case MADE_PROGRESS_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.MADE_PROGRESS_SHORT_QUESTION);
            case PLAYING_CD_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.PLAYING_CD_SHORT_QUESTION);
            case PLAYING_DVD_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.PLAYING_DVD_SHORT_QUESTION);
            case POLISH_SPEAKING_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.POLISH_SPEAKING_SHORT_QUESTION);
            case USEING_PROJECTOR_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.USEING_PROJECTOR_SHORT_QUESTION);
            case USE_LECTOR_BLOG_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.USE_LECTOR_BLOG_SHORT_QUESTION);
            case WORKING_METHOD_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.WORKING_METHOD_SHORT_QUESTION);
            case YOUR_TIME_LEARNING_QUESTION:
                return GUIGenerator.getInstance().getLocaleText(Trans.YOUR_TIME_LEARNING_SHORT_QUESTION);
            default:
                return GUIGenerator.getInstance().getLocaleText(question);
        }
    }

    private Double parseValue(String type, String value) {
        switch (type) {
            case RATE_4:
                return Double.parseDouble(value) * 6;
            case RATE_6:
                return Double.parseDouble(value) * 6;
            case ALLWAYS_RATE:
                return Double.parseDouble(value) * 5;
            case TIME_LEARNING_LESS_20_MIN_RATE:
                return Double.parseDouble(value) * 5;
            case YES_RATE:
                return Double.parseDouble(value) * 5;
            case TOO_MUCH_RATE:
                return Double.parseDouble(value) * 5;
            case RATE_5:
                return Double.parseDouble(value) * 5;
            case OFTEN_RATE:
                return Double.parseDouble(value) * 3;
            case TIME_LEARNING_30_MIN_RATE:
                return Double.parseDouble(value) * 3;
            case NO_RATE:
                return Double.parseDouble(value) * 2;
            case TIME_LEARNING_HOUR_RATE:
                return Double.parseDouble(value) * 2;
            case TOO_LESS_RATE:
                return Double.parseDouble(value) * 3;
            case RATE_3:
                return Double.parseDouble(value) * 3;
            case NEVER_RATE:
                return Double.parseDouble(value) * 2;
            case EMPTY_RATE:
                return Double.parseDouble(value) * 2;
            case RATE_2:
                return Double.parseDouble(value) * 2;
            case TIME_LEARNING_MORE_HOUR_RATE:
                return Double.parseDouble(value) * 1;
            default:
                return Double.parseDouble(value) * 1;
        }
    }
}
